import axios from 'axios'
import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError,
  CancelTokenSource
} from 'axios'
import { message } from 'antd'

// 类型定义
export interface ApiResponse<T = any> {
  code: number
  msg: string
  data: T
}

interface ApiError {
  code: number
  msg: string
  isAxiosError: boolean
  originalError?: any
}

interface HttpClientConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
  cancelKey?: string
}

// 创建 axios 实例
const createAxiosInstance = (config: AxiosRequestConfig): AxiosInstance => {
  const instance = axios.create(config)

  // 请求拦截器
  instance.interceptors.request.use(
    config => {
      const token = localStorage.getItem('token')
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }

      if (config.showLoading) {
        message.loading({
          content: '加载中...',
          key: 'loading',
          duration: 0
        })
      }

      return config
    },
    error => Promise.reject(error)
  )

  // 响应拦截器
  instance.interceptors.response.use(
    (response: AxiosResponse<ApiResponse>) => {
      if (response.config.showLoading) {
        message.destroy('loading')
      }

      if (response.data.code !== 200) {
        return Promise.reject({
          code: response.data.code,
          msg: response.data.msg || '业务错误',
          isAxiosError: false
        })
      }
      return response.data.data
    },
    (error: AxiosError) => {
      if (error.config?.showLoading) {
        message.destroy('loading')
      }

      if (axios.isCancel(error)) {
        return Promise.reject({
          code: -1,
          message: '请求已取消',
          isAxiosError: true,
          originalError: error
        })
      }

      const apiError: ApiError = {
        code: error.response?.status || 500,
        msg: error.response?.data?.msg || error.message,
        isAxiosError: true,
        originalError: error
      }

      if (error.config?.showError !== false) {
        handleGlobalError(apiError)
      }

      return Promise.reject(apiError)
    }
  )

  return instance
}

// 全局错误处理
const handleGlobalError = (error: ApiError) => {
  if (!error.isAxiosError && error.code !== 200) {
    message.error(error.msg || '业务错误')
    return
  }

  switch (error.code) {
    case 401:
      message.error('未授权，请重新登录')
      window.location.href = '/login'
      break
    case 403:
      message.error('拒绝访问')
      break
    case 404:
      message.error('资源不存在')
      break
    case 500:
      message.error('服务器错误')
      break
    default:
      message.error(error.msg || '网络错误')
  }
}

// 创建实例
const httpInstance = createAxiosInstance({
  // baseURL: import.meta.env.VITE_API_BASE_URL,
  baseURL: 'http://localhost:8087',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 请求取消相关
const cancelTokenMap = new Map<string, CancelTokenSource>()

const cancelRequest = (key: string) => {
  if (cancelTokenMap.has(key)) {
    cancelTokenMap.get(key)?.cancel('请求被取消')
    cancelTokenMap.delete(key)
  }
}

// 核心请求函数
const request = async <T>(
  method: 'get' | 'post' | 'put' | 'delete' | 'patch',
  url: string,
  data?: any,
  config?: HttpClientConfig
): Promise<T> => {
  let requestConfig: HttpClientConfig = { ...config }
  // 处理取消请求
  if (config?.cancelKey) {
    const source = axios.CancelToken.source()
    cancelTokenMap.set(config.cancelKey, source)
    requestConfig.cancelToken = source.token
  }
  try {
    let response: AxiosResponse<T, any, {}>
    switch (method) {
      case 'get':
        response = await httpInstance.get<T>(url, requestConfig)
        break
      case 'post':
        response = await httpInstance.post<T>(url, data, requestConfig)
        break
      case 'put':
        response = await httpInstance.put<T>(url, data, requestConfig)
        break
      case 'delete':
        response = await httpInstance.delete<T>(url, requestConfig)
        break
      case 'patch':
        response = await httpInstance.patch<T>(url, data, requestConfig)
        break
    }
    return response
  } catch (error) {
    return Promise.reject(error)
  }
}

// 导出常用方法
const http = {
  get: <T>(url: string, config?: HttpClientConfig) =>
    request<T>('get', url, undefined, config),
  post: <T>(url: string, data?: any, config?: HttpClientConfig) =>
    request<T>('post', url, data, config),
  put: <T>(url: string, data?: any, config?: HttpClientConfig) =>
    request<T>('put', url, data, config),
  delete: <T>(url: string, config?: HttpClientConfig) =>
    request<T>('delete', url, undefined, config),
  patch: <T>(url: string, data?: any, config?: HttpClientConfig) =>
    request<T>('patch', url, data, config),
  uploadFile: <T>(
    url: string,
    file: File,
    onUploadProgress?: (progressEvent: ProgressEvent) => void
  ) => {
    const formData = new FormData()
    formData.append('file', file)
    return request<T>('post', url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress
    })
  },
  cancelRequest: cancelRequest
}
export default http
